<?php

class ModelActiverecordLibYeti extends BaseActiverecordLibYeti implements ModelInterfaceYeti {

    
    
    public function colString($col) {
        $col = (!is_array($col)) ? func_get_args() : $col;
        $this->setColumns($col, 'string');
    }    
    
    public function colInt($col) {
        $col = (!is_array($col)) ? func_get_args() : $col;
        $this->setColumns($col, 'int');
    }
    
    public function colBinary($col) {
        $col = (!is_array($col)) ? func_get_args() : $col;
        $this->setColumns($col, 'binary');
    }
    
    public function colEnum($col) {
        $col = (!is_array($col)) ? func_get_args() : $col;
        $this->setColumns($col, 'enum');
    }
    
    public function colDate($col) {
        $col = (!is_array($col)) ? func_get_args() : $col;
        $this->setColumns($col, 'date');
    }
    
    public function colDatetime($col) {
        $col = (!is_array($col)) ? func_get_args() : $col;
        $this->setColumns($col, 'datetime');
    }
    
    public function setReadonly($column) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        $this->columns[$column]['readonly'] = TRUE;
    }
    
    public function setInvisible($column) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        $this->columns[$column]['invisible'] = TRUE;
    }
    
    public function setPrimaryKey($column) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        $this->columns[$column]['is_primary'] = TRUE;
    }
    
    public function setForeignKey($arr) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        // Informa a chave estrangeira
    }
    
    
    private function setColumns(array $columns, $type) {
        foreach($columns as $alias => $name) {
            if(!is_string($alias)) {
                $alias = $name;
            }
            
            $this->columns[$alias] = Array('name' => $name, 'type' => $type);
        }
    }
    
    public function __set($var, $value) {
        if(isset($this->columns[$var])) {
            $this->setValue($var, $value);
        }
    }
    
    public function save(array $data = Array()) {
        
    }    
    
    public function first($order = 'Pk') {
        return $this->order_asc($order)->find(1);
    }
    
    public function last($order = 'Pk') {
        return $this->order_desc($order)->find(1);
    }
    
    public function any($column, array $args) {
        $is_true = false;
        $this->openClausule();
        
        foreach($args as $expr) {
            ($is_true) ? $this->operator("OR") : $is_true = TRUE;
            
            $this->filter($column, $expr);
        }
        
        $this->endClausule();
        
        return $this;
    }
    
    private function resolveNamesColumn($column) {
        if(($pos = stripos($column, '.')) !== FALSE) {
            $exp = explode('.', $column);
            return Array($exp[1], $exp[0]);
        }
        
        return Array($column, $this->table);
    }
    
    public function parserFilter_eq($column, $cond) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        list($column, $table) = $this->resolveNamesColumn($column);
        
        if(is_array($cond)) {
            $condition = Array();
            
            foreach(explode(',', $cond) as $listCond) {
                $condition[] = $this->quote($listCond, $column);
            }
            
            return " {$table}.{$column} IN (" . implode(',', $condition) . ")";
        }

        $cond = $this->quote($cond, $column);
        return " {$table}.{$column} = {$cond}";
    }
    
    public function parserFilter_not($column, $cond) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        list($column, $table) = $this->resolveNamesColumn($column);
        
        if(is_array($cond)) {
            $condition = Array();
            
            foreach(explode(',', $cond) as $listCond) {
                $condition[] = $this->quote($listCond, $column);
            }
            
            return " {$table}.{$column} NOT IN (" . implode(',', $condition) . ")";
        }

        $cond = $this->quote($cond, $column);
        return " {$table}.{$column} != {$cond}";
    }
    
    public function parserFilter_gte($column, $cond) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        if(!is_scalar($cond)) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        list($column, $table) = $this->resolveNamesColumn($column);
        
        return " {$table}.{$column} >= {$this->quote($cond, $column)}";
    }
    
    public function parserFilter_gt($column, $cond) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        if(!is_scalar($cond)) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        list($column, $table) = $this->resolveNamesColumn($column);
        
        return " {$table}.{$column} > {$this->quote($cond, $column)}";
    }
    
    public function parserFilter_lte($column, $cond) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        if(!is_scalar($cond)) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        list($column, $table) = $this->resolveNamesColumn($column);
        
        return " {$table}.{$column} <= {$this->quote($cond, $column)}";
    }
    
    public function parserFilter_lt($column, $cond) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        if(!is_scalar($cond)) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        list($column, $table) = $this->resolveNamesColumn($column);
        
        return " {$table}.{$column} < {$this->quote($cond, $column)}";
    }
    
    public function parserFilter_like($column, $cond) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        if(!is_scalar($cond)) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        list($column, $table) = $this->resolveNamesColumn($column);
        
        return " {$table}.{$column} LIKE {$this->quote($cond, $column)}";
    }
    
    public function parserFilter_likel($column, $cond) {
        return $this->parserFilter_like($column, "%{$cond}");
    }
    
    public function parserFilter_liker($column, $cond) {
        return $this->parserFilter_like($column, "{$cond}%");
    }
    
    public function parserFilter_likelr($column, $cond) {
        return $this->parserFilter_like($column, "%{$cond}%");
    }
    
    public function parserFilter_between($column, $cond) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        if(!is_array($cond)) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        if(count($cond) != 2) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        list($column, $table) = $this->resolveNamesColumn($column);
        
        return " {$table}.{$column} BETWEEN {$this->quote($cond[0], $column)} AND {$this->quote($cond[1], $column)}";
    }
    
    /*public function parserFilter_function($column, $function, array $args = Array()) {
        if(strlen($column) && !isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        
    }*/
    
    private function parserFilterArr(array $condition, $table = NULL) {
        $rules = Array();
        
        if(is_null($table)) {
            $table = $this->table;
        }
        
        foreach($condition as $method => $args) {
            $method = strtolower($method);
            
            if($method == 'operator') {
                $rules[] = $this->parseOperator($args);
                continue;
            }
            elseif($method == 'clausule') {
                $rules[] = $this->parseClausule($args ? 'open' : 'end');
                continue;
            }
            
            $method = "parserFilter_{$method}";
            
            if(is_null($table)) {
                list($column, $table) = $this->resolveNamesColumn(array_shift($args));
            }
            else {
                $column = $table . '.' . array_shift($args);
            }
            
            $rules[] = $this->$method($column, (isset($args[1]) ? $args : $args[0]));
        }
        
        return $rules;
    }
    
    public function find($limit = NULL, $offset = NULL) {
        if(is_numeric($limit)) {
            $this->query_limit = $limit;
            
            if(is_numeric($offset)) {
                $this->query_offset = $offset;
            }
        }
        
        return $this->driver->executeQuery($this->getArrQuery());;
    }
    
    public function getSql($limit = NULL, $offset = NULL) {
        if(is_numeric($limit)) {
            $this->query_limit = $limit;
            
            if(is_numeric($offset)) {
                $this->query_offset = $offset;
            }
        }
        
        return $this->driver->makeSql($this->getArrQuery());;
    }
    
    public function order(array $columns) {
        foreach($columns as $column => $order) {
            $order = strtolower($order);
            $method = "order_{$order}";
            $this->$method($column);
        }
        
        return $this;
    }
    
    public function order_asc() {
        foreach(func_get_args() as $column) {
            if(!isset($this->columns[$column])) {
                throw new ActiverecordPluginYetiException('__');
            }
            
            $this->query_order[] = $column . " ASC";
        }
        
        return $this;
    }
    
    public function order_desc() {
        foreach(func_get_args() as $column) {
            if(!isset($this->columns[$column])) {
                throw new ActiverecordPluginYetiException('__');
            }
            
            $this->query_order[] = $column . " DESC";
        }
        
        return $this;
    }
    
    public function group($column) {
        if(!isset($this->columns[$column])) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        $this->query_group[] = $column;
        return $this;
    }
    
    
    private function addFilter($column, $cond) {
        $condition = (count($this->query_filter) > 0) ? " {$this->getOperator()} " : "";
        $this->query_filter[] = "{$condition} {$column} {$cond}";
    }
    
    public function filter($column, $cond) {
        $this->addFilter($this->parserFilter_eq($column, $cond));
        return $this;
    }
    
    public function filter_not($column, $cond) {
        $this->addFilter($this->parserFilter_not($column, $cond));
        return $this;
    }
    
    public function filter_gte($column, $cond) {
        $this->addFilter($this->parserFilter_gte($column, $cond));
        return $this;
    }
    
    public function filter_lte($column, $cond) {
        $this->addFilter($this->parserFilter_lte($column, $cond));
        return $this;
    }
    
    public function filter_gt($column, $cond) {
        $this->addFilter($this->parserFilter_gt($column, $cond));
        return $this;
    }
    
    public function filter_lt($column, $cond) {
        $this->addFilter($this->parserFilter_lt($column, $cond));
        return $this;
    }
    
    public function filter_like($column, $cond) {
        $this->addFilter($this->parserFilter_like($column, $cond));
        return $this;
    }
    
    public function filter_likel($column, $cond) {
        $this->addFilter($this->parserFilter_likel($column, $cond));
        return $this;
    }
    
    public function filter_liker($column, $cond) {
        $this->addFilter($this->parserFilter_liker($column, $cond));
        return $this;
    }
    
    public function filter_likelr($column, $cond) {
        $this->addFilter($this->parserFilter_likelr($column, $cond));
        return $this;
    }
    
    public function filter_between($column, array $cond) {
        $this->addFilter($this->parserFilter_between($column, $cond));
        return $this;
    }
    
    
    private function addHaving($cond) {
        $condition = (count($this->query_having) > 0) ? " {$this->getOperator()} " : "";
        $this->query_having[] = "{$condition} {$cond}";
    }
    
    public function having($column, $cond) {
        $this->addHaving($this->parserFilter_eq($column, $cond));
        return $this;
    }
    
    public function having_not($column, $cond) {
        $this->addHaving($this->parserFilter_not($column, $cond));
        return $this;
    }
    
    public function having_gte($column, $cond) {
        $this->addHaving($this->parserFilter_gte($column, $cond));
        return $this;
    }
    
    public function having_lte($column, $cond) {
        $this->addHaving($this->parserFilter_lte($column, $cond));
        return $this;
    }
    
    public function having_gt($column, $cond) {
        $this->addHaving($this->parserFilter_gt($column, $cond));
        return $this;
    }
    
    public function having_lt($column, $cond) {
        $this->addHaving($this->parserFilter_lt($column, $cond));
        return $this;
    }
    
    public function having_like($column, $cond) {
        $this->addHaving($this->parserFilter_like($column, $cond));
        return $this;
    }
    
    public function having_likel($column, $cond) {
        $this->addHaving($this->parserFilter_likel($column, $cond));
        return $this;
    }
    
    public function having_liker($column, $cond) {
        $this->addHaving($this->parserFilter_liker($column, $cond));
        return $this;
    }
    
    public function having_likelr($column, $cond) {
        $this->addHaving($this->parserFilter_likelr($column, $cond));
        return $this;
    }
    
    public function having_between($column, array $cond) {
        $this->addHaving($this->parserFilter_between($column, $cond));
        return $this;
    }
    
    private function addJoin($type, $table, array $condition = Array(), $makeRel = TRUE) {
        if($makeRel) {
            // fazer engenharia reversa para localizar relacionamento
            //array_unshift($condition, $relationship);
        }
        
        $this->query_join["{$type}::{$table}"] = $condition;
    }
    
    public function join($table, array $condition = Array(), $makeRel = TRUE) {
        $this->inner_join($table, $condition, $makeRel);
        return $this;
    }
    
    public function left_join($table, array $condition = Array(), $makeRel = TRUE) {
        if(!is_string($table)) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        $this->addJoin('left', $table, $this->parserFilterArr($condition, $table), $makeRel);
        return $this;
    }
    
    public function right_join($table, array $condition = Array(), $makeRel = TRUE) {
        if(!is_string($table)) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        $this->addJoin('right', $table, $this->parserFilterArr($condition, $table), $makeRel);
        return $this;
    }
    
    public function inner_join($table, array $condition = Array(), $makeRel = TRUE) {
        if(!is_string($table)) {
            throw new ActiverecordPluginYetiException('__');
        }
        
        $this->addJoin('inner', $table, $this->parserFilterArr($condition, $table), $makeRel);
        return $this;
    }
    
    
}
